package models

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/websocket"
	"gopkg.in/fatih/set.v0"
	"gorm.io/gorm"
	"net"
	"net/http"
	"strconv"
	"sync"
)

type Message struct {
	gorm.Model
	FromId   int64  `json:"from_id"`   // 消息发送者id
	TargetId int64  `json:"target_id"` // 消息接收者id
	Content  string `json:"content"`   // 消息内容
	Media    int    `json:"media"`     // 消息类型 1: 文本 2: 图片 3: 语音 4: 视频
	Type     int    `json:"type"`      // 消息类型 1: 私聊 2: 群聊 3: 广播
	Status   int    `json:"status"`
	Pic      string `json:"pic"`    // 图片消息的缩略图
	Url      string `json:"url"`    // 视频消息的缩略图
	Desc     string `json:"desc"`   // 视频消息的描述
	Amount   int    `json:"amount"` // 其他字数统计
}

func (table *Message) TableName() string {
	return "message"
}

type Node struct {
	Conn      *websocket.Conn
	DataQueue chan []byte
	// go get gopkg.in/fatih/set.v0
	// 引入set
	GroupSets set.Interface
}

// 映射关系
var clientMap map[int64]*Node = make(map[int64]*Node)

// 读写锁
var rwLocker sync.RWMutex

func Chat(writer http.ResponseWriter, request *http.Request) {
	// 校验token
	query := request.URL.Query()
	userId := query.Get("user_id")
	userIdInt, _ := strconv.ParseInt(userId, 10, 64)
	//targetId := query.Get("target_id")
	//content := query.Get("content")
	//msgType := query.Get("type")
	isValida := true // 这里需要检查token是否有效
	conn, err := (&websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return isValida
		},
	}).Upgrade(writer, request, nil)

	if err != nil {
		return
	}

	// 2 获取conn
	node := &Node{
		Conn:      conn,
		DataQueue: make(chan []byte),
		GroupSets: set.New(set.ThreadSafe),
	}

	// 3 用户关系

	// 4 把userid和node绑定并且加锁
	rwLocker.Lock()
	clientMap[userIdInt] = node
	rwLocker.Unlock()
	// 5 完成发送逻辑
	go sendProc(node)
	// 6 完成接受逻辑
	go recvProc(node)
	// 显示欢迎消息
	fmt.Println("发送消息给userId=", userId)
	sendMsg(userIdInt, []byte("欢迎来到小熊聊天室"))
}

func sendProc(node *Node) {
	for {
		select {
		case data := <-node.DataQueue:
			err := node.Conn.WriteMessage(websocket.TextMessage, data)
			if err != nil {
				fmt.Println("发送失败", err)
				return
			}
		}
	}
}

func recvProc(node *Node) {
	for {
		_, data, err := node.Conn.ReadMessage()
		if err != nil {
			fmt.Println("接收失败", err)
			return
		}
		// 消息广播到局域网

		fmt.Println("接收成功", string(data))
	}
}

// 定义一个管道
var udpsendChan chan []byte = make(chan []byte, 1000)

func broadMsg(data []byte) {
	udpsendChan <- data
}

func init() {
	go udpSendProc()
	go udpRecvProc()
}

// 完成udp数据发送协程
func udpSendProc() {
	udp, err := net.DialUDP("udp", nil, &net.UDPAddr{
		IP:   net.ParseIP("127.0.0.1"),
		Port: 3000,
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	defer func(udp *net.UDPConn) {
		err := udp.Close()
		if err != nil {

		}
	}(udp)

	// 循环发送数据
	for {
		data := <-udpsendChan
		_, err := udp.Write(data)
		if err != nil {
			fmt.Println(err)
			return
		}
	}
}

// 完成udp数据接收协程
func udpRecvProc() {
	udp, err := net.ListenUDP("udp", &net.UDPAddr{
		IP:   net.ParseIP("127.0.0.1"),
		Port: 3000,
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	defer func(udp *net.UDPConn) {
		err := udp.Close()
		if err != nil {

		}
	}(udp)

	// 循环接收数据
	for {
		data := make([]byte, 1024)
		n, addr, err := udp.ReadFromUDP(data)
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println("收到数据", string(data[:n]), addr)
	}
}

// 后端调度逻辑处理
func dispatch(data []byte) {
	msg := Message{}
	err := json.Unmarshal(data, &msg)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(msg)
	switch msg.Type {
	case 1:
		sendMsg(msg.FromId, []byte(msg.Content)) // 私聊
	//case 2:
	//	sendGroup(msg) // 群聊
	//case 3:
	//	sendAllMsg(msg) // 广播
	default:
		break
	}
}

func sendMsg(userId int64, msg []byte) {
	rwLocker.RLock()
	node, ok := clientMap[userId]
	rwLocker.RUnlock()
	if ok {
		node.DataQueue <- msg
	}

}
